﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Media;
using System.Windows;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;

namespace dmm
{
    public enum VideoSourceType
    {
        VideoFromLocal,
        VideoFromRecord,
        VideoFromConversion,
    };


   public class StreamInfo
    {
        public int Id
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }

    }

    public class Video :INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

       
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public const int VIDEO_EDIT_TRIM = 0x01;
        public const int VIDEO_EDIT_CROP =0x02;

        
        #region basic property in databse
        private string name;
        private string thumbnail;
        private string path;
        private string profile;
        private VideoSourceType srctype;
        //file info
        private double duration = 100;
        private int size = 0;//file size

        private int width;
        private int height;
        //format
        private string container;
        private string vcodec;
        private string acodec;
        //video source url
        private string url;

        private string create_date;
        private string desc;

        private Int64 rowid;

        private double fps;
        #endregion

        //some movie timestamp are not start from 0.0
        public double StartTime
        {
            get;
            set;
        }

        public List<StreamInfo> audio_streams = new List<StreamInfo>();
        public List<StreamInfo> sub_streams = new List<StreamInfo>();
       public int selected_aid = -1;
       public int selected_tid = -1;
        


        private VideoEditSetting setting;


        public Video()
        {
            StartTime = 0;
            StreamInfo info = new StreamInfo();
            info.Id = -1;
            info.Name = "default";

            audio_streams.Add(info);
            sub_streams.Add(info);
        }

        public void add_audio_stream(int id){
            bool exist = false;

            foreach (StreamInfo info in audio_streams)
            {
                if (info.Id == id)
                {
                    exist = true;
                    break;
                }
            }

            if (!exist)
            {
                StreamInfo info = new StreamInfo();
                info.Id = id;
                info.Name = String.Format("aid {0}", id);
                audio_streams.Add(info);
                OnPropertyChanged("AUDIO_STREAM");
            }
        }

        public void add_subtitle_stream(int id)
        {
            bool exist = false;

            foreach (StreamInfo info in sub_streams)
            {
                if (info.Id == id)
                {
                    exist = true;
                    break;
                }
            }

            if (!exist)
            {
                StreamInfo info = new StreamInfo();
                info.Id = id;
                info.Name = String.Format("tid {0}", id);
                sub_streams.Add(info);
                OnPropertyChanged("SUBTITLE_STREAM");
            }
        }

        private bool dirty = false;

        public VideoEditSetting VideoSetting
        {
            get { return setting; }
            set { 
                setting = value;
            }
        }
        

        public string CreateDate
        {
            get { return create_date; }
            set { create_date = value; dirty = true; }
        }
        public Int64 ID
        {
            get { return rowid; }
            set { rowid = value; }
        }
        public string URL
        {
            get { return url; }
            set { dirty = true; url = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; dirty = true; }
        }
        public string Thumbnail
        {
            get 
            {
                try
                {
                    if (File.Exists(thumbnail))
                        return thumbnail;
                    else
                        return "pack://siteoforigin:,,,/img/vob.bmp";
                }
                catch (Exception)
                {
                           return "pack://siteoforigin:,,,/img/vob.bmp";
                }
            }
            set {
                if (thumbnail != null && thumbnail != value)
                {
                  if(File.Exists(thumbnail))
                      File.Delete(thumbnail);
                }
                thumbnail = value; 
                dirty = true;
                OnPropertyChanged("Thumbnail");
            }
        }
        public string Url
        {
            get { return url; }
            set { url = value; dirty = true; }
        }
        public string Path
        {
            get { return path; }
            set { path = value; dirty = true; }
        }
        public  string Dimension
        {
            get { return width + "x" + height; }
        }
        public double Duration
        {
            get { return duration; }
            set { duration = value;
            OnPropertyChanged("Duration");
                dirty = true; }
        }
        public  string Format
        {
            get { return container + "-->[ " + vcodec + "/" + acodec+"]"; }
        }

        public int Width
        {
            get { return width; }
            set { 
                width = value;
                OnPropertyChanged("Dimension");
                dirty = true; 
            }
        }
        public int Height
        {
            get { return height; }
            set { 
                height = value;
                OnPropertyChanged("Dimension");
                dirty = true; 
            }
        }

        //v.Container, v.Vcodec, v.Acodec, v.Desc,v.Srctype,v.Profile);
        public string Container
        {
            get { return container; }
            set { container = value; dirty = true; }
        }

        public string Vcodec
        {
            get { return vcodec; }
            set { vcodec = value; dirty = true; }
        }

        public string Acodec
        {
            get { return acodec; }
            set { acodec = value; dirty = true; }
        }

        public VideoSourceType Srctype
        {
            get { return srctype; }
            set { srctype = value; dirty = true; }
        }

        public string Profile
        {
            get { return profile; }
            set { profile = value; dirty = true; }
        }

        public string Desc
        {
            get { return desc; }
            set { desc = value; dirty = true; }
        }

        public bool IsDirty
        {
            get { return dirty; }
            set { dirty = value; }
        }

        public  string FileName
        {
            get
            {
                return System.IO.Path.GetFileName(path);
            }
        }

        public string FileNameNoExt
        {
            get
            {
                return System.IO.Path.GetFileNameWithoutExtension(path);
            }
        }

        public  string FileExt
        {
            get
            {
                return System.IO.Path.GetExtension(path);
            }
        }
        
       
        /*public bool load_video(string sname, string spath)
        {
            name = sname;
            path = spath;

            thumbnail = null;
            return true;
        }*/

        public bool is_cropped()
        {
            return (setting != null) && ((setting.edit_flag & VIDEO_EDIT_CROP) != 0);
        }

        public bool is_trimed()
        {
            return (setting != null) && ((setting.edit_flag & VIDEO_EDIT_TRIM) != 0);
        }

        public void write_edl()
        {
            
            using (StreamWriter stream = new StreamWriter(Options.Instance.EdlOutPath+@"\edl"+this.rowid+".txt"))
            {
                string seg0 = String.Format("{0:0.0}\t{1:0.0}\t{2}\r\n", 0, setting.trim_start + StartTime, 0);
                stream.Write(seg0);

                string seg1 = String.Format("{0:0.0}\t{1:0.0}\t{2}\r\n", setting.trim_end+StartTime, this.duration+StartTime, 0);
                stream.Write(seg1);
            }
        }

        public void trim(double st,double end)
        {
            if (setting == null) 
                setting = VideoEditSettings.add_setting(ID);

            setting.edit_flag |= VIDEO_EDIT_TRIM;
            setting.trim_start = st ;
            setting.trim_end = end ;

            //use edl ?
            write_edl();
        }

        public void untrim(){
            setting.edit_flag &= ~VIDEO_EDIT_TRIM;
            setting.trim_start = setting.trim_end = 0;
            if (setting.edit_flag == 0) 
                VideoEditSettings.remove_setting(ID);
            
        }

        //all params are in [0---1] std space
        public void crop(double left, double top, double w, double h)
        {
            if (setting == null) 
                setting = VideoEditSettings.add_setting(ID);
            setting.edit_flag |= VIDEO_EDIT_CROP;
            setting.crop_rect.X = left;
            setting.crop_rect.Y = top;
            setting.crop_rect.Width = w;
            setting.crop_rect.Height = h;
        }

        public void uncrop()
        {
            setting.edit_flag &= ~VIDEO_EDIT_CROP;
            setting.crop_rect.X = setting.crop_rect.Y = 0;
            setting.crop_rect.Width = setting.crop_rect.Height = 0;
            if (setting.edit_flag == 0)
                VideoEditSettings.remove_setting(ID);

        }

        
    }
}
